import axios from "axios";
import { useAppStore } from "@/store/modules/app";
import { dayjs, ElMessage as Message } from "element-plus";
import { getLocalStorage } from "@/utils/tools";
import { getToken, removeToken } from "@/utils/auth";
import { baseUrl } from "@/config";
import { tansParams, checkType } from "./tools";

type Methods = "GET" | "POST" | "PUT" | "DELETE";

interface IHttpOptions {
  isLoading?: boolean;
  isFormData?: boolean;
  isMessage?: boolean;
  [key: string]: any;
}

export interface HttpResponse<T = any> {
  data: T;
  code: number;
  message: any;
  [key: string]: any;
}

axios.defaults.withCredentials = true; // 跨域访问需要发送cookie时一定要加这句

let httpTime = 0;

// 添加请求拦截器，在发送请求之前做些什么
axios.interceptors.request.use(
  function (config) {
    httpTime++;
    const appStore = useAppStore();
    // 可以记录请求的取消函数
    const CancelToken = axios.CancelToken;
    // xhr.abort() 终端请求方法
    config.cancelToken = new CancelToken((c) => {
      // c就是当前取消请求的token
      appStore.addCancelTokens(c);
    });
    return config;
  },
  function (error) {
    return Promise.reject(error);
  }
);

// 添加响应拦截器
axios.interceptors.response.use(
  function (response) {
    // 对响应数据做点什么，允许在数据返回客户端前，修改响应的数据
    return response.data;
  },
  function (error) {
    return Promise.reject(error);
  }
);

// 封装axios
function HttpRequest<T = any>(
  url: string,
  method: Methods,
  params: any = {},
  options: IHttpOptions = {
    isLoading: false,
    isFormData: false,
    isMessage: true, // 是否要提示信息
  }
): Promise<HttpResponse<T>> {
  const appStore = useAppStore();
  if (options.isLoading && method === "GET" && !appStore.loading) {
    appStore.loading = true;
  }
  // 设置token
  const token = getToken();

  // POST PUT 转表单格式提交
  const formData = new FormData();
  if (method === "POST" || method === "PUT") {
    Object.keys(params).forEach((key) => {
      formData.append(key, params[key]);
    });
  }
  const httpDefault = {
    baseURL: baseUrl,
    method,
    url,
    headers: {
      withCredentials: true,
      Authorization: "Bearer " + encodeURIComponent(token as string), // 请求头不能有中文
      language: getLocalStorage("locale") || "zh-cn",
      "Content-Type": "application/json; charset=utf-8",
    },
    params: method === "GET" || method === "DELETE" ? params : null,
    data:
      method === "POST" || method === "PUT"
        ? options.isFormData
          ? formData
          : params
        : null,
    timeout: 60000,
  };
  return new Promise((resolve, reject) => {
    axios(httpDefault)
      .then(async (response: any) => {
        if (method !== "GET") {
          if (options.isMessage) {
            if (response.code === 500) {
              Message.error(response.message);
              throw new Error(response.message);
            } else {
              Message.success(response.message);
            }
          }
        } else if (method === "GET") {
          if (response.data && checkType.isObject(response.data)) {
            if (response.data.created_date) {
              response.data.created_date = dayjs(
                response.data.created_date
              ).format("YYYY-MM-DD HH:mm:ss");
            }
            if (response.data.updated_date) {
              response.data.updated_date = dayjs(
                response.data.updated_date
              ).format("YYYY-MM-DD HH:mm:ss");
            }
          }
          if (
            response.data &&
            response.data.lists &&
            checkType.isArray(response.data.lists)
          ) {
            response.data.lists.forEach((item: any) => {
              if (item.created_date) {
                item.created_date = dayjs(item.created_date).format(
                  "YYYY-MM-DD HH:mm:ss"
                );
              }
              if (item.updated_date) {
                item.updated_date = dayjs(item.updated_date).format(
                  "YYYY-MM-DD HH:mm:ss"
                );
              }
            });
          }
        }
        resolve(response);
      })
      .catch((error) => {
        error.response?.data?.message &&
          Message.error(error.response?.data?.message);
        if (error.response?.status === 401) {
          removeToken();
          window.location.reload();
        }
        reject(error);
      })
      .then(function () {
        httpTime--;
        if (!httpTime) {
          appStore.loading = false;
        }
      });
  });
}

interface IDownLoadOption {
  url: string;
  filename: string;
  params?: Object;
}
// 流下载文件
export function downLoad(option: IDownLoadOption) {
  const params = option.params ? option.params : {};
  return axios
    .post(baseUrl + option.url, params, {
      transformRequest: [
        (params) => {
          return tansParams(params);
        },
      ],
      headers: {
        withCredentials: true,
        Authorization: "Bearer " + getToken(),
        "Content-Type": "application/x-www-form-urlencoded",
      },
      responseType: "blob",
    })
    .then((data: any) => {
      const content = data;
      const blob = new Blob([content]);
      const elink = document.createElement("a");
      elink.download = option.filename;
      elink.style.display = "none";
      elink.href = URL.createObjectURL(blob);
      document.body.appendChild(elink);
      elink.click();
      URL.revokeObjectURL(elink.href);
      document.body.removeChild(elink);
    })
    .catch((r) => {
      console.error(r);
    });
}

export function downfileUrl(url: string) {
  const link = document.createElement("a");
  link.href = baseUrl + url;
  link.setAttribute("target", "_blank");
  link.click();
}

export default HttpRequest;
